package com.shop.controller;

import com.alibaba.druid.util.StringUtils;
import com.shop.captcha.CaptchaCodeManager;
import com.shop.pojo.DtsAdmin;
import com.shop.service.DtsPermissionService;
import com.shop.service.DtsRoleService;
import com.shop.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Auth 认证。此类是登录认证写的
 *
 * @ClassName LoginAuthController
 * @Author xiao宋
 * @Date 20:03  2022/10/12
 * @Version 1.0
 * @Description TODO
 */
//@CrossOrigin("http://localhost")
@Slf4j
@RestController
@RequestMapping("/admin/auth")
public class LoginAuthController {
    @Autowired
    DtsRoleService roleService;
    @Autowired
    DtsPermissionService permissionService;

    /**
     * 登录二次请求所需要的用户角色数据
     * @return  data={
     *          "roles",
     *          "name",
     *          "perms",
     *          "avatar"}
     */
    @RequestMapping("/info")
    public Object info() {
        Subject subject = SecurityUtils.getSubject();
        DtsAdmin admin = (DtsAdmin) subject.getPrincipal();

        Set<String> roles = roleService.findRolesById(admin.getRoleIds());

        Set<String> perms = permissionService.findPermsById(admin.getRoleIds());

        Map<String, Object> data = new HashMap<>();

//        分别加上前端需要的数据并返回
        data.put("roles", roles);//角色
        data.put("perms", perms);//权限
        data.put("name", admin.getUsername());//用户名
        data.put("avatar", admin.getAvatar());//头像地址
        return ResponseUtil.ok(data);
    }

    /**
     * 主页登录生成验证码并上传
     */
    @RequestMapping("/captchaImage")
    public Object captchaImage() throws IOException {
//        需要一个参数 验证码的个数
        String code = VerifyCodeUtils.generateVerifyCode(1);
        String uuid = UUID.randomUUID().toString();
//       在缓存区储存验证码               验证码有效期设置   5  （分钟）
        CaptchaCodeManager.addToCache(uuid, code, 5);
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
//        用流返回验证码                 宽度、高度、流、验证码
        VerifyCodeUtils.outputImage(120, 40, bo, code);
        Map<String, Object> map = new HashMap<>();
        map.put("img", Base64.encode(bo.toByteArray()));
        map.put("uuid", uuid);

        return ResponseUtil.ok(map);
    }
    /**
     * 登录调用
     * 由于前端传的是JSON数据所以得用 @RequestBody 接收数据
     *
     * @param map
     */
    @RequestMapping("/login")
    public Object login(@RequestBody Map<String, String> map, HttpSession session) {
//        拿到用户输入的信息
        String username = map.get("username");
        String password = map.get("password");
        String inputCode = map.get("code");
        String uuid = map.get("uuid");
        log.info("拿到了用户信息");
        System.err.println("用户名" + username);
        System.err.println("密码" + password);

        // 前端返回的数据，再判断一下，总没有错。
        if (StringUtils.isEmpty(username) ||
                StringUtils.isEmpty(password) ||
                StringUtils.isEmpty(inputCode) ||
                StringUtils.isEmpty(uuid)) {
            return ResponseUtil.badArgument();
        }
//          获取缓存里的验证码  并判断一下用户输入的是否正确
        String code = CaptchaCodeManager.getCachedCaptcha(uuid);
        if (!inputCode.equalsIgnoreCase(code)) {
            return AdminResponseUtil.fail(AdminResponseCode.AUTH_CAPTCHA_ERROR);
        }
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            return ResponseUtil.fail(-1, "账户是未知的");
        } catch (LockedAccountException e) {
            e.printStackTrace();
            return ResponseUtil.fail(-1, "该账户已失效");
        } catch (CredentialsException e) {
            e.printStackTrace();
            return ResponseUtil.fail(-1, "密码错误");
        } catch (AuthenticationException e) {
            e.printStackTrace();
            log.info("认证出现错误：LoginAuthController--> 100行");
            return ResponseUtil.fail(-1, "账户认证错误");
        }
//        前端需要sessionID。所以得返回一个
        String data = session.getId();
        return ResponseUtil.ok(data);
    }
}
